#include "cvrealtimepaint.h"
#include <QList>
#include <QPainter>
#include <QPen>
#include <QGraphicsItem>
// #include "kzfqgraphicslineitem.h"
#include "kzfqgraphicsellipseitem.h"
// #include "kzfqgraphicsrectitem.h"
#include "kzfqgraphicsitemgroup.h"

//----------------------------------------------------------------------------------------
drawListItem::drawListItem(int type)
{
    if(type<typeMax){
        drawingType = type;
    }else{
        drawingType = typeLine;
    }

    switch(drawingType){
        case typeLine:
            maxPoints = 2;
            break;
        case typeAngle:
            maxPoints = 3;
            break;
        case typeRect:
            maxPoints = 4;
            break;
        case typeCircle:
            maxPoints = 3;
            break;
        case typePolygons:
            maxPoints = 100;
            break;
        default:break;
    }
    drawPointNum = 0;
    isValid = 0;
    drawPoints.clear();
}

bool drawListItem::drawAddPoint(QPointF point)
{
    // qDebug()<<"drawAddPoint new drawAddPoint"<<point;

    if(drawPointNum<maxPoints){
        drawPointNum++;
        drawPoints.append(point);
        return true;
    }
    qDebug()<<"drawAddPoint new drawAddPoint false"<<point;
    return false;
}

bool drawListItem::drawSubPoint(void)
{
    // qDebug()<<"new drawSubPoint"<<point;

    if(drawPointNum>0){
        drawPointNum--;
        drawPoints.removeLast();
        return true;
    }
    return false;
}
//========================================================================================





//----------------------------------------------------------------------------------------
cvRealtimePaint::cvRealtimePaint(QObject *parent) : QObject{parent}
{
    drawingType = typeNull;
    drawingStatus = waitingFristPoint;
    drawingLists.clear();
    DrawScene.clear();
    umPerPixel = 1.0;

    // QPen pen;   // 定义一个画笔，设置画笔颜色和宽度
    pen.setColor(QColor(255, 0, 0));
    pen.setWidth(1);
    brush_color.setAlpha(0);//0透明
    brush.setColor(brush_color);

}

void cvRealtimePaint::setPixelGain(float in)
{
    umPerPixel = in;
}


void cvRealtimePaint::dataReset()
{
    drawingLists.clear();
}

void cvRealtimePaint::cleanInvalidPoints(void)
{   int i = 0;
    // qDebug()<<"cleanInvalidPoints befor:"<<drawingLists.length();

    //删去未画完的点
    foreach (drawListItem list, drawingLists) {
        if(list.isValid==false){
            drawingLists.removeAt(i);
        }
        i++;
    }
    // qDebug()<<"cleanInvalidPoints after:"<<drawingLists.length();

    //删去未画完的item
    for(;;){
        QList<QGraphicsItem *> gv_items = DrawScene.items();//把确定的item放到场景众
        // qDebug()<<"cleanInvalidPoints dll item:"<<gv_items.length()<<drawingLists.length();
        if(gv_items.length()>drawingLists.length()){
            DrawScene.removeItem(gv_items.first());
            // qDebug()<<"cleanInvalidPoints dll item after:"<<gv_items.length();
            DrawScene.update();
        }else{
            // qDebug()<<"cleanInvalidPoints dll item end:"<<gv_items.length();
            break;
        }
    }
}

bool cvRealtimePaint::drawingNullMode(void)
{
    drawingType = typeNull;
    drawingStatus = waitingFristPoint;
    cleanInvalidPoints();
    return true;
}

bool cvRealtimePaint::drawingLineMode(void)
{
    drawingType = typeLine;
    drawingStatus = waitingFristPoint;

    qDebug()<<"drawingLineMode"<<"draw type"<<drawingType<<"status:"<<drawingStatus;
    return true;
}

bool cvRealtimePaint::drawingCircleMode(void)
{
    drawingType = typeCircle;
    drawingStatus = waitingFristPoint;

    qDebug()<<"drawingLineMode"<<"draw type"<<drawingType<<"status:"<<drawingStatus;
    return true;
}

bool cvRealtimePaint::drawingAngleMode(void)
{

    drawingType = typeAngle;
    drawingStatus = waitingFristPoint;

    qDebug()<<"drawingLineMode"<<"draw type"<<drawingType<<"status:"<<drawingStatus;
    return true;
}

bool cvRealtimePaint::drawingSquarenessMode(void)
{

    drawingType = typeRect;
    drawingStatus = waitingFristPoint;

    qDebug()<<"drawingLineMode"<<"draw type"<<drawingType<<"status:"<<drawingStatus;
    return true;
}

bool cvRealtimePaint::drawingPolygeonMode(void)
{

    drawingType = typePolygons;
    drawingStatus = waitingFristPoint;

    qDebug()<<"drawingLineMode"<<"draw type"<<drawingType<<"status:"<<drawingStatus;
    return true;
}

bool  cvRealtimePaint::drawingDelLastItem(void)
{
    if(drawingLists.length()>1){
        drawingLists.removeLast();
        return true;
    }

    return false;
}


void cvRealtimePaint::slots_mouse_left_press(QMouseEvent *event)
{
    switch(drawingType){
        case (int)cvRealtimePaint::typeLine:

            #if 0
            //如果是第一个点,只增加点到item
            //如果是第二个点,增加到item,并完成直线绘制,更新sence,使其valid有效
            if(drawingStatus == waitingFristPoint){
                drawingStatus = waitingMoving;
                drawListItem *item = new drawListItem(drawListItem::typeLine);
                item->drawAddPoint(event->pos());
                drawingLists.append(*item);//item_list
            }else if(drawingStatus == drawingGraph){
                drawingStatus = waitingFristPoint;
                drawingLists.back().isValid = true;
                drawingLists.back().drawPoints.replace(1, event->pos());//替换最直线点

                QList<QGraphicsItem *> gv_items = DrawScene.items();//把确定的item放到场景众
                if(gv_items.length()){
                    DrawScene.removeItem(gv_items.first());//删除最后放入的一个item
                }
                kzfQGraphicsLineItem *newLineItem = new kzfQGraphicsLineItem(QLineF(drawingLists.back().drawPoints.at(0), drawingLists.back().drawPoints.at(1)));
                newLineItem->setPen(pen);
                DrawScene.addItem(newLineItem);
                DrawScene.update();//更新显示
            }
            #endif

            #if 1//用group作直线
            //如果是第一个点,只增加点到item
            //如果是第二个点,增加到item,并完成直线绘制,更新sence,使其valid有效
            if(drawingStatus == waitingFristPoint){
                drawingStatus = waitingMoving;
                drawListItem *item = new drawListItem(drawListItem::typeLine);
                item->drawAddPoint(event->pos());
                drawingLists.append(*item);//item_list
            }else if(drawingStatus == drawingGraph){
                drawingStatus = waitingFristPoint;
                drawingLists.back().isValid = true;
                drawingLists.back().drawPoints.replace(1, event->pos());//替换最直线点

                QList<QGraphicsItem *> gv_items = DrawScene.items();//把确定的item放到场景众
                if(gv_items.length()){
                    DrawScene.removeItem(gv_items.first());//删除最后放入的一个item
                }

                kzfQGraphicsItemGroup *newLineItem = new kzfQGraphicsItemGroup();
                QPointF *one = new QPointF(drawingLists.back().drawPoints.at(0).x(), drawingLists.back().drawPoints.at(0).y());
                QPointF *two = new QPointF(drawingLists.back().drawPoints.at(1).x(), drawingLists.back().drawPoints.at(1).y());
                double x = drawingLists.back().drawPoints.at(0).x() - drawingLists.back().drawPoints.at(1).x();
                double y = drawingLists.back().drawPoints.at(0).y() - drawingLists.back().drawPoints.at(1).y();
                x = x * x;
                y = y * y;
                x = sqrt(x+y);
                newLineItem->setLineGroup(*one, *two, umPerPixel * x);

                DrawScene.addItem(newLineItem);
                DrawScene.update();//更新显示
            }
            #endif

            break;

        case cvRealtimePaint::typeAngle:

            break;

        case cvRealtimePaint::typeRect:

            break;

        case cvRealtimePaint::typeCircle:
            //三点画圆  都画在圆弧上
            if(drawingStatus == waitingFristPoint){
                drawingStatus = waitingMoving;
                drawListItem *item = new drawListItem(drawListItem::typeCircle);
                item->drawAddPoint(event->pos());
                drawingLists.append(*item);//item_list
            }else if(drawingStatus == drawingGraph){
                if(drawingLists.back().drawPointNum==2){
                    drawingLists.back().drawPoints.replace(1, event->pos());//替换最直线点
                    drawingLists.back().drawAddPoint(event->pos());
                }else if(drawingLists.back().drawPointNum==3){
                    drawingStatus = waitingFristPoint;
                    drawingLists.back().isValid = true;

                    QList<QGraphicsItem *> gv_items = DrawScene.items();
                    if(gv_items.length()){
                        DrawScene.removeItem(gv_items.first()->parentItem());//删除最后一个item
                    }
                    drawingLists.back().drawPoints.replace(2, event->pos());//替换最直线点

                    QRectF * tmpRect= PointsToQtCircle(drawingLists.back().drawPoints.at(0), drawingLists.back().drawPoints.at(1), drawingLists.back().drawPoints.at(2));
                    kzfQGraphicsEllipseItem *newCircleItem = new kzfQGraphicsEllipseItem(*tmpRect);
                    newCircleItem->setPen(pen);
                    newCircleItem->setBrush(brush);
                    DrawScene.addItem(newCircleItem);
                }
            }
            break;

        case cvRealtimePaint::typePolygons:

            break;

        case cvRealtimePaint::typeCaliCircle:
            // {
            //     QList<QGraphicsItem *> gv_items = DrawScene.items();
            //     foreach (QGraphicsItem *i, gv_items) {

            //     }
            // }
            break;

        case cvRealtimePaint::typeCaliLine:

            break;

        default:break;
    }

}

void cvRealtimePaint::slots_mouse_right_press(QMouseEvent *event)
{
    switch(drawingType){
    case (int)cvRealtimePaint::typeLine://删点
        #if 0
        //删掉直线的点,删掉场景的item重新进入等待第一个点状态
        if(drawingLists.back().isValid==false){
            if(drawingLists.back().drawPointNum>1){

                QList<QGraphicsItem *> gv_items = DrawScene.items();
                if(gv_items.length()){
                    DrawScene.removeItem(gv_items.first());//删除最后一个item
                }
                DrawScene.update();

                drawingStatus = waitingFristPoint;
                drawingLists.removeLast();
            }
        }
        #endif

        #if 1//用group作直线
        //删掉直线的点,删掉场景的item重新进入等待第一个点状态
        if(drawingLists.back().isValid==false){
            if(drawingLists.back().drawPointNum>1){

                QList<QGraphicsItem *> gv_items = DrawScene.items();
                if(gv_items.length()){
                    DrawScene.removeItem(gv_items.first()->parentItem());//删除最后一个item
                }
                DrawScene.update();

                drawingStatus = waitingFristPoint;
                drawingLists.removeLast();
            }
        }
        #endif
        break;

    case cvRealtimePaint::typeAngle:

        break;

    case cvRealtimePaint::typeRect:

        break;

    case cvRealtimePaint::typeCircle:
        if(drawingLists.back().isValid==false){
            if(drawingLists.back().drawPointNum==2){
                QList<QGraphicsItem *> gv_items = DrawScene.items();
                if(gv_items.length()){
                    DrawScene.removeItem(gv_items.first());//删除最后一个item
                }

                DrawScene.update();

                drawingStatus = waitingFristPoint;
                drawingLists.removeLast();
            }else if(drawingLists.back().drawPointNum==3){
                drawingLists.back().drawSubPoint();

                QList<QGraphicsItem *> gv_items = DrawScene.items();
                if(gv_items.length()){
                    DrawScene.removeItem(gv_items.first());//删除最后一个item
                }

                drawingLists.back().drawPoints.replace(1, event->pos());
                QRectF * tmpRect= PointsToQtCircle(drawingLists.back().drawPoints.at(0), drawingLists.back().drawPoints.at(1), drawingLists.back().drawPoints.at(1));
                kzfQGraphicsEllipseItem *newCircleItem = new kzfQGraphicsEllipseItem(*tmpRect);
                newCircleItem->setPen(pen);
                newCircleItem->setBrush(brush);
                DrawScene.addItem(newCircleItem);

                DrawScene.update();
            }
        }
        break;

    case cvRealtimePaint::typePolygons:

        break;
    default:break;
    }
}

void cvRealtimePaint::slots_mouse_release(QMouseEvent *event)
{
    // qDebug()<<"rlp slots_mouse_release";

}

void cvRealtimePaint::slots_mouse_move(QMouseEvent *event)
{

    if(drawingStatus==waitingFristPoint){
        return;
    }

    switch(drawingType){
        case typeLine:
            #if 0   //只有直线
            //画一条直线
            if(drawingStatus == waitingMoving){
                drawingStatus = drawingGraph;
                drawingLists.back().drawAddPoint(event->pos());//添加第二个点
                kzfQGraphicsLineItem *newLineItem = new kzfQGraphicsLineItem(QLineF(drawingLists.back().drawPoints.at(0), drawingLists.back().drawPoints.at(1)));
                newLineItem->setPen(pen);
                DrawScene.addItem(newLineItem);
            }else{
                QList<QGraphicsItem *> gv_items = DrawScene.items();
                if(gv_items.length()){
                    DrawScene.removeItem(gv_items.first());//删除最后一个item
                }

                drawingLists.back().drawPoints.replace(1, event->pos());//替换最直线点
                kzfQGraphicsLineItem *newLineItem = new kzfQGraphicsLineItem(QLineF(drawingLists.back().drawPoints.at(0), drawingLists.back().drawPoints.at(1)));
                newLineItem->setPen(pen);
                DrawScene.addItem(newLineItem);
            }

            DrawScene.update();//更新显示
            #endif

            #if 1//用group作直线
            //画一条直线
            if(drawingStatus == waitingMoving){
                drawingStatus = drawingGraph;
                drawingLists.back().drawAddPoint(event->pos());//添加第二个点
                kzfQGraphicsItemGroup *newLineItem = new kzfQGraphicsItemGroup();
                QPointF *one = new QPointF(drawingLists.back().drawPoints.at(0).x(), drawingLists.back().drawPoints.at(0).y());
                QPointF *two = new QPointF(drawingLists.back().drawPoints.at(1).x(), drawingLists.back().drawPoints.at(1).y());
                // newLineItem->setLineGroup(*one, *two, 112.32);
                double x = drawingLists.back().drawPoints.at(0).x() - drawingLists.back().drawPoints.at(1).x();
                double y = drawingLists.back().drawPoints.at(0).y() - drawingLists.back().drawPoints.at(1).y();
                x = x * x;
                y = y * y;
                x = sqrt(x+y);
                newLineItem->setLineGroup(*one, *two, umPerPixel * x);

                DrawScene.addItem(newLineItem);
            }else{
                QList<QGraphicsItem *> gv_items = DrawScene.items();
                if(gv_items.length()){
                    DrawScene.removeItem(gv_items.first()->parentItem());//删除最后一个item
                }
                drawingLists.back().drawPoints.replace(1, event->pos());//替换最直线点

                kzfQGraphicsItemGroup *newLineItem = new kzfQGraphicsItemGroup();
                QPointF *one = new QPointF(drawingLists.back().drawPoints.at(0).x(), drawingLists.back().drawPoints.at(0).y());
                QPointF *two = new QPointF(drawingLists.back().drawPoints.at(1).x(), drawingLists.back().drawPoints.at(1).y());
                // newLineItem->setLineGroup(*one, *two, 112.32);

                double x = drawingLists.back().drawPoints.at(0).x() - drawingLists.back().drawPoints.at(1).x();
                double y = drawingLists.back().drawPoints.at(0).y() - drawingLists.back().drawPoints.at(1).y();
                x = x * x;
                y = y * y;
                x = sqrt(x+y);
                newLineItem->setLineGroup(*one, *two, umPerPixel * x);

                DrawScene.addItem(newLineItem);
            }

            DrawScene.update();//更新显示
            #endif

            break;

        case typeAngle:

            break;

        case typeRect:

            break;

        case typeCircle:
            //画圆
            if(drawingStatus == waitingMoving){
                drawingStatus = drawingGraph;
                drawingLists.back().drawAddPoint(event->pos());//添加第二个点
                if(drawingLists.back().drawPointNum==2){
                    QRectF * tmpRect= PointsToQtCircle(drawingLists.back().drawPoints.at(0), drawingLists.back().drawPoints.at(1), drawingLists.back().drawPoints.at(1));
                    kzfQGraphicsEllipseItem *newCircleItem = new kzfQGraphicsEllipseItem(*tmpRect);
                    newCircleItem->setPen(pen);
                    newCircleItem->setBrush(brush);
                    DrawScene.addItem(newCircleItem);
                }
            }else if(drawingStatus == drawingGraph){
                QList<QGraphicsItem *> gv_items = DrawScene.items();
                if(gv_items.length()){
                    DrawScene.removeItem(gv_items.first());//删除最后一个item
                }

                if(drawingLists.back().drawPointNum==2){
                    drawingLists.back().drawPoints.replace(1, event->pos());
                    QRectF * tmpRect= PointsToQtCircle(drawingLists.back().drawPoints.at(0), drawingLists.back().drawPoints.at(1), drawingLists.back().drawPoints.at(1));
                    kzfQGraphicsEllipseItem *newCircleItem = new kzfQGraphicsEllipseItem(*tmpRect);
                    newCircleItem->setPen(pen);
                    newCircleItem->setBrush(brush);
                    DrawScene.addItem(newCircleItem);
                }else if(drawingLists.back().drawPointNum==3){
                    drawingLists.back().drawPoints.replace(2, event->pos());
                    QRectF * tmpRect= PointsToQtCircle(drawingLists.back().drawPoints.at(0), drawingLists.back().drawPoints.at(1), drawingLists.back().drawPoints.at(2));
                    // qDebug()<<"circle move rect 2:"<<tmpRect->topLeft()<<tmpRect->size();
                    kzfQGraphicsEllipseItem *newCircleItem = new kzfQGraphicsEllipseItem(*tmpRect);
                    newCircleItem->setPen(pen);
                    newCircleItem->setBrush(brush);
                    DrawScene.addItem(newCircleItem);
                }
            }
            DrawScene.update();//更新显示
            break;

        case typePolygons:

            break;
        default:break;
    }

    DrawScene.update();//更新显示
}

//========================================================================================

//----------------------------------------------------------------------------------------
QRectF* cvRealtimePaint::PointsToQtCircle(QPointF p1, QPointF p2, QPointF p3)
{
    //圆上3个点确认一个圆
    //根据每个点到圆形距离一样的公式计算
    // QRectF *recRect = new QRectF();

    float a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, det = 0, cx = 0, cy = 0, r;

    if(p2.x()==p3.x()&& p2.y()==p3.y()){
        //后面两个点一样,就用前两二点经过的圆心作圆
        cx = p1.x() + (p2.x() - p1.x()) / 2;
        cy = p1.y() + (p2.y() - p1.y()) / 2;//圆心

        r = sqrt( abs(p2.x() - p1.x()) * abs(p2.x() - p1.x()) + abs(p2.y() - p1.y()) * abs(p2.y() - p1.y()) ) / 2; //半径
        QRectF *recRect = new QRectF(QPointF(cx-r, cy-r), QPointF(cx+r, cy+r));

        return recRect;
    }

    a = p1.x() - p2.x();
    b = p1.y() - p2.y();
    c = p1.x() - p3.x();
    d = p1.y() - p3.y();
    e = ((p1.x() * p1.x() - p2.x() * p2.x()) + (p1.y() * p1.y() - p2.y() * p2.y())) / 2.0;
    f = ((p1.x() * p1.x() - p3.x() * p3.x()) + (p1.y() * p1.y() - p3.y() * p3.y())) / 2.0;
    det = b * c - a * d;

    if(qAbs(det)<1e-5){
        //计算失败
        QRectF *recRect = new QRectF(QPointF(0, 0), QSizeF(0, 0));//QRectF(const QPointF &topleft, const QSizeF &size) noexcept;
        return recRect;
    }

    cx = -(d * e - b * f) / det;
    cy = -(a * f - c * e) / det;//圆心
    r = hypot((p1.x() - cx), (p1.y()- cy));//半径

    QRectF *recRect = new QRectF(QPointF(cx-r, cy-r), QPointF(cx+r, cy+r));
    return recRect;
}

//========================================================================================

/*
    画出图片中识别到的圆  cboxs 圆的坐标列表
*/
void cvRealtimePaint::manualDrawCircle(QList<QRectF> cboxs)
{
    qDebug()<<"manualDrawCircle"<<cboxs.length();

    foreach(QRectF x, cboxs) {
        kzfQGraphicsEllipseItem *newCircleItem = new kzfQGraphicsEllipseItem(x);
        newCircleItem->setPen(pen);
        newCircleItem->setBrush(brush);
        DrawScene.addItem(newCircleItem);
    }
    
    DrawScene.update();
}
